package com.mugui.sql;

import lombok.Getter;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.sql.DataSource;

class SqlUtils {
    private DataSource dataSource;

    private Connection connection = null;

    private PreparedStatement preparedStatement = null;

    private ResultSet resultSet = null;

    public SqlUtils() {
        this.dataSource = DBConf.getDefaultDBConf().getDataSource();
    }

    public SqlUtils(DBConf dbConf) {
        this.dataSource = dbConf.getDataSource();
    }

    public Connection getConnection() throws SQLException {
        if (connection == null) {
            connection = dataSource.getConnection();
            if (!autoCommit)
                connection.setAutoCommit(false);
            return connection;
        }
        return connection;
    }

    private boolean lock_of_update = false;

    public void setLockOfSelect(boolean lock_of_update) {
        this.lock_of_update = lock_of_update;
    }

    public ResultSet select(String sql, Object[] parvar) throws SQLException {
        if (sql == null)
            throw new NullPointerException("SQL is null");
        if (lock_of_update) {
            sql += " for update";
        }
        preparedStatement = handerParameter(sql, parvar);
        return resultSet = preparedStatement.executeQuery();
    }

    private PreparedStatement handerParameter(String sql, Object[] parvar) throws SQLException {
        preparedStatement = getConnection().prepareStatement(sql);
        if (parvar != null && parvar.length > 0)
            for (int i = 0; i < parvar.length; ++i) {
                if (parvar[i] == null)
                    continue;
                Object o = parvar[i];
                if(o instanceof Date){
                    long millis=((Date) o).getTime();
                    millis = (millis + 500) / 1000 * 1000; // 四舍五入到秒
                    o=new Date(millis);
                }
                preparedStatement.setObject(i + 1, o);
            }
        return preparedStatement;
    }

    public int update(String sql, Object[] parvar) throws SQLException {
        if (sql == null)
            throw new NullPointerException("SQL is null");
        preparedStatement = handerParameter(sql, parvar);
        return preparedStatement.executeUpdate();
    }

    public void Close() {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            resultSet = null;
        }
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            preparedStatement = null;
        }
        if (connection != null && autoCommit) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            connection = null;
        }
    }

    //强制回收
    public void forceClose() {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            resultSet = null;
        }
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            preparedStatement = null;
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            connection = null;
        }
    }

    /**
     * 不可靠的检测
     *
     * @return
     * @throws SQLException
     * @auther 木鬼
     */
    @Deprecated
    public boolean isClose() throws SQLException {
        return connection.isClosed();
    }

    /**
     * 批量执行
     *
     * @param sqls
     * @throws SQLException
     * @auther 木鬼
     */
    public void batch(String[] sqls) throws SQLException {
        if (sqls == null || sqls.length == 0)
            throw new NullPointerException("SQL is null");
        boolean autoCommit = connection.getAutoCommit();
        Statement statement = connection.createStatement();
        for (String sql : sqls) {
            statement.addBatch(sql);
        }
        statement.executeBatch();
        statement.clearBatch();
        statement.close();
        if (autoCommit) {
            connection.commit();
            connection.setAutoCommit(true);
            Close();
        }
    }

    public void rollback() {
        if (connection != null && !autoCommit) {
            try {
                connection.rollback();
                autoCommit = true;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 提交事务,并开启自动提交
     *
     * @throws SQLException
     */
    public void commit() throws SQLException {
        if (connection != null && !autoCommit) {
            connection.commit();
        }
    }

    @Getter
    private boolean autoCommit = true;

    public void setAutoCommit(boolean bool) throws SQLException {
        lock_of_update = false;
        autoCommit = bool;
        if (connection != null) {
            connection.setAutoCommit(autoCommit);
        }
    }


}